#include "setting.h"
#include "at24cxx.h"
#include "stm32f1xx_hal.h"
#include <stdlib.h>
#include <string.h>
#include <netdev_ipaddr.h>
#include <rtdevice.h>

#define AT24CXX_BUS_NAME "i2c1"
static at24cxx_device_t at24cxx_dev = RT_NULL;

device_param_t device_setting = RT_NULL;

void setting_init(void)
{
    at24cxx_dev = at24cxx_init(AT24CXX_BUS_NAME, RT_NULL);
    if (!at24cxx_dev)
    {
        rt_kprintf("EEPROM Device Error!\n");
        rt_thread_mdelay(1000);
        rt_hw_cpu_reset();
    }
    device_setting = rt_calloc(1, sizeof(struct device_param));
    if (device_setting == RT_NULL)
    {
        rt_kprintf("Can't allocate memory for device_setting.");
        rt_thread_mdelay(1000);
        rt_hw_cpu_reset();
    }
    //读取
    at24cxx_read(at24cxx_dev, 0x00, (uint8_t *)device_setting, sizeof(struct device_param));
    //第一次进行初始配置
    if(device_setting->fun_type == 0xFF)
    {
        setting_set_default();
    }
}

void setting_set_default(void)
{
    device_setting->fun_type = FUN_TYPE_MQTT2RTU;
    device_setting->fun_enable = 0;
    device_setting->down_dev = 0;
    device_setting->platform_type = PLATFORM_TYPE_ALIYUN;

    device_setting->rs232_params.baud = BAUD_RATE_9600;
    device_setting->rs232_params.parity = PARITY_NONE;
    device_setting->rs232_params.data_bit = DATA_BITS_8;
    device_setting->rs232_params.stop_bit = STOP_BITS_1;

    device_setting->rs485_params.baud = BAUD_RATE_9600;
    device_setting->rs485_params.parity = PARITY_NONE;
    device_setting->rs485_params.data_bit = DATA_BITS_8;
    device_setting->rs485_params.stop_bit = STOP_BITS_1;

    device_setting->netdev_params.netdev_type = NETDEV_TYPE_ESP8266;
    device_setting->netdev_params.dhcp = 1;
    inet_aton("192.168.1.123", &device_setting->netdev_params.ip_addr);
    inet_aton("255.255.255.0", &device_setting->netdev_params.netmask);
    inet_aton("192.168.1.1", &device_setting->netdev_params.gw);
    inet_aton("192.168.1.1", &device_setting->netdev_params.dns_servers[0]);
    inet_aton("192.168.1.1", &device_setting->netdev_params.dns_servers[1]);
    union share_RAM{ uint32_t mcu_id[3]; uint8_t hwaddr[24];}x;
    x.mcu_id[0] = HAL_GetUIDw0();
    x.mcu_id[1] = HAL_GetUIDw1();
    x.mcu_id[2] = HAL_GetUIDw2();
    device_setting->netdev_params.hwaddr[0] = 0x00;
    device_setting->netdev_params.hwaddr[1] = x.hwaddr[2];
    device_setting->netdev_params.hwaddr[2] = x.hwaddr[1];
    device_setting->netdev_params.hwaddr[3] = x.hwaddr[0];
    device_setting->netdev_params.hwaddr[4] = x.hwaddr[7];
    device_setting->netdev_params.hwaddr[5] = x.hwaddr[6];
    device_setting->netdev_params.hwaddr[6] = x.hwaddr[5];
    device_setting->netdev_params.hwaddr[7] = x.hwaddr[4];

    strcpy(device_setting->cellular_params.apn, "CMNET");

    strcpy(device_setting->wifi_params.ssid, "CMCC-ew69");
    strcpy(device_setting->wifi_params.password, "tn6xhxnr");

    strcpy(device_setting->server_params.host, "192.168.1.4");
    device_setting->server_params.port = 127;

    at24cxx_write(at24cxx_dev, 0x00, (uint8_t *)device_setting, sizeof(struct device_param));
    //读取
    at24cxx_read(at24cxx_dev, 0x00, (uint8_t *)device_setting, sizeof(struct device_param));
}

static int setting(int argc, char **argv)
{
    uint8_t err = RT_ERROR;
    uint32_t WriteAddr;
    if (!strcmp(argv[1], "get"))
    {
        if(!strcmp(argv[2], "fun_type"))
        {
            rt_kprintf("fun_type:%d\n", device_setting->fun_type);
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "down_dev"))
        {
            rt_kprintf("down_dev:%d\n", device_setting->down_dev);
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "platform_type"))
        {
            rt_kprintf("platform_type:%d\n", device_setting->platform_type);
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "rs232"))
        {
            rt_kprintf("baud:%d\n", device_setting->rs232_params.baud);
            rt_kprintf("parity:%d\n", device_setting->rs232_params.parity);
            rt_kprintf("data_bit:%d\n", device_setting->rs232_params.data_bit);
            rt_kprintf("stop_bit:%d\n", device_setting->rs232_params.stop_bit);
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "rs485"))
        {
            rt_kprintf("baud:%d\n", device_setting->rs485_params.baud);
            rt_kprintf("parity:%d\n", device_setting->rs485_params.parity);
            rt_kprintf("data_bit:%d\n", device_setting->rs485_params.data_bit);
            rt_kprintf("stop_bit:%d\n", device_setting->rs485_params.stop_bit);
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "netdev"))
        {
            rt_kprintf("netdev_type:%d\n", device_setting->netdev_params.netdev_type);
            rt_kprintf("dhcp:%d\n", device_setting->netdev_params.dhcp);
            rt_kprintf("ip_addr:%s\n", inet_ntoa(device_setting->netdev_params.ip_addr));
            rt_kprintf("netmask:%s\n", inet_ntoa(device_setting->netdev_params.netmask));
            rt_kprintf("gw:%s\n", inet_ntoa(device_setting->netdev_params.gw));
            rt_kprintf("dns_servers1:%s\n", inet_ntoa(device_setting->netdev_params.dns_servers[0]));
            rt_kprintf("dns_servers2:%s\n", inet_ntoa(device_setting->netdev_params.dns_servers[1]));
            rt_kprintf("mac:%02x:%02x:%02x:%02x:%02x:%02x\n", device_setting->netdev_params.hwaddr[0],
                    device_setting->netdev_params.hwaddr[1],
                    device_setting->netdev_params.hwaddr[2],
                    device_setting->netdev_params.hwaddr[3],
                    device_setting->netdev_params.hwaddr[4],
                    device_setting->netdev_params.hwaddr[5]);
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "cellular"))
        {
            rt_kprintf("apn:%s\n", device_setting->cellular_params.apn);
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "wifi"))
        {
            rt_kprintf("ssid:%s \npassword:%s\n", device_setting->wifi_params.ssid, device_setting->wifi_params.password);
            err = RT_EOK;
        }
        else if (!strcmp(argv[2], "server"))
        {
            rt_kprintf("host:%s port:%d\n", device_setting->server_params.host, device_setting->server_params.port);
            err = RT_EOK;
        }
        else
        {
            err = RT_ERROR;
        }
    }
    else if(!strcmp(argv[1], "set"))
    {
        if(!strcmp(argv[2], "default"))
        {
            setting_set_default();
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "fun_type"))
        {
            device_setting->fun_type = atoi(argv[3]);
            WriteAddr = (uint8_t *)&device_setting->fun_type - (uint8_t *)device_setting;
            at24cxx_write(at24cxx_dev, WriteAddr, (uint8_t *)&device_setting->fun_type, sizeof(uint8_t));
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "down_dev"))
        {
            device_setting->down_dev = atoi(argv[3]);
            WriteAddr = (uint8_t *)&device_setting->down_dev - (uint8_t *)device_setting;
            at24cxx_write(at24cxx_dev, WriteAddr, (uint8_t *)&device_setting->down_dev, sizeof(uint8_t));
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "platform_type"))
        {
            device_setting->platform_type = atoi(argv[3]);
            WriteAddr = (uint8_t *)&device_setting->platform_type - (uint8_t *)device_setting;
            at24cxx_write(at24cxx_dev, WriteAddr, (uint8_t *)&device_setting->platform_type, sizeof(uint8_t));
            err = RT_EOK;
        }
        else if(!strcmp(argv[2], "rs232"))
        {
            if(argc == 7)
            {
                device_setting->rs232_params.baud = atoi(argv[3]);
                device_setting->rs232_params.parity = atoi(argv[4]);
                device_setting->rs232_params.data_bit = atoi(argv[5]);
                device_setting->rs232_params.stop_bit = atoi(argv[6]);
                WriteAddr = (uint8_t *)&device_setting->rs232_params - (uint8_t *)device_setting;
                at24cxx_write(at24cxx_dev, WriteAddr, (uint8_t *)&device_setting->rs232_params, sizeof(struct uart_param));
                err = RT_EOK;
            }
        }
        else if(!strcmp(argv[2], "rs485"))
        {
            if(argc == 7)
            {
                device_setting->rs485_params.baud = atoi(argv[3]);
                device_setting->rs485_params.parity = atoi(argv[4]);
                device_setting->rs485_params.data_bit = atoi(argv[5]);
                device_setting->rs485_params.stop_bit = atoi(argv[6]);
                WriteAddr = (uint8_t *)&device_setting->rs485_params - (uint8_t *)device_setting;
                at24cxx_write(at24cxx_dev, WriteAddr, (uint8_t *)&device_setting->rs485_params, sizeof(struct uart_param));
                err = RT_EOK;
            }
        }
        else if(!strcmp(argv[2], "netdev"))
        {
            if(argc == 5)
            {
                if(!strcmp(argv[3], "netdev_type"))
                {
                    device_setting->netdev_params.netdev_type = atoi(argv[4]);
                    err = RT_EOK;
                }
                else if (!strcmp(argv[3], "dhcp"))
                {
                    device_setting->netdev_params.dhcp = atoi(argv[4]);
                    err = RT_EOK;
                }
                else if(!strcmp(argv[3], "dns"))
                {
                    inet_aton(argv[4], &device_setting->netdev_params.dns_servers[0]);
                    err = RT_EOK;
                }
                else
                {
                    inet_aton(argv[3], &device_setting->netdev_params.ip_addr);
                    inet_aton(argv[4], &device_setting->netdev_params.netmask);
                    err = RT_EOK;
                }
            }
            else if (argc == 4)
            {
                inet_aton(argv[3], &device_setting->netdev_params.ip_addr);
                err = RT_EOK;
            }
            else if (argc == 6)
            {
                if(!strcmp(argv[3], "dns"))
                {
                    inet_aton(argv[4], &device_setting->netdev_params.dns_servers[0]);
                    inet_aton(argv[5], &device_setting->netdev_params.dns_servers[1]);
                    err = RT_EOK;
                }
                else
                {
                    inet_aton(argv[3], &device_setting->netdev_params.ip_addr);
                    inet_aton(argv[4], &device_setting->netdev_params.netmask);
                    inet_aton(argv[5], &device_setting->netdev_params.gw);
                    err = RT_EOK;
                }
            }
            if(err == RT_EOK)
            {
                WriteAddr = (uint8_t *)&device_setting->netdev_params - (uint8_t *)device_setting;
                at24cxx_write(at24cxx_dev, WriteAddr, (uint8_t *)&device_setting->netdev_params, sizeof(struct netdev_param));
            }

        }
        else if(!strcmp(argv[2], "cellular"))
        {
            if(argc == 5)
            {
                if(!strcmp(argv[3], "apn"))
                {
                    strcpy(device_setting->cellular_params.apn, argv[4]);
                    WriteAddr = (uint8_t *)&device_setting->cellular_params - (uint8_t *)device_setting;
                    at24cxx_write(at24cxx_dev, WriteAddr, (uint8_t *)&device_setting->cellular_params, sizeof(struct cellular_param));
                    err = RT_EOK;
                }
            }
        }
        else if(!strcmp(argv[2], "wifi"))
        {
            if(argc == 5)
            {
                strcpy(device_setting->wifi_params.ssid, argv[3]);
                strcpy(device_setting->wifi_params.password, argv[4]);
                WriteAddr = (uint8_t *)&device_setting->wifi_params - (uint8_t *)device_setting;
                at24cxx_write(at24cxx_dev, WriteAddr, (uint8_t *)&device_setting->wifi_params, sizeof(struct wifi_param));
                err = RT_EOK;
            }
        }
        else if(!strcmp(argv[2], "server"))
        {
            if(argc == 5)
            {
                strcpy(device_setting->server_params.host, argv[3]);
                device_setting->server_params.port = atoi(argv[4]);
                WriteAddr = (uint8_t *)&device_setting->server_params - (uint8_t *)device_setting;
                at24cxx_write(at24cxx_dev, WriteAddr, (uint8_t *)&device_setting->server_params, sizeof(struct server_param));
                err = RT_EOK;
            }
        }
        else
        {
            err = RT_ERROR;
        }
        rt_thread_mdelay(100);
        //读取
        at24cxx_read(at24cxx_dev, 0x00, (uint8_t *)device_setting, sizeof(struct device_param));
    }
    if(err == RT_ERROR)
    {
        rt_kprintf("setting param error!\n");
    }
    return err;
}
MSH_CMD_EXPORT(setting, set setting param);

void get_device_id(uint32_t *mcu_id)
{
//    char device_id[25];
//    unsigned short mcu_flash_size;
    mcu_id[0] = HAL_GetUIDw0();
    mcu_id[1] = HAL_GetUIDw1();
    mcu_id[2] = HAL_GetUIDw2();
//    rt_sprintf(device_id, "%08X%08X%08X",mcu_id[0],mcu_id[1],mcu_id[2]);
//    mcu_flash_size = *(unsigned short*)(0x1FFFF7E0);
//    rt_kprintf("MCU Flash size: %d K\n",mcu_flash_size);
}

static int device_id()
{
    uint32_t mcu_id[3];
    get_device_id(mcu_id);
    rt_kprintf("device_id:%08X%08X%08X\n",mcu_id[0],mcu_id[1],mcu_id[2]);
    return RT_EOK;
}
MSH_CMD_EXPORT(device_id, get device id);
